# X11 の PCF ビットマップフォントファイルのフォーマット

このファイルは X11 のソースに基づいています。ソースに書かれている内容と何らかの食い違いがあれば、私の記述が間違っています。ソースが定義です。

PCF (portable compile format) ファイルフォーマットは X サーバが使用するビットマップフォントの倍なり表現です。ファイルヘッダに続き一連のテーブルと、すべてのテーブルにへのポインタを含むヘッダが続きます。

## ファイルヘッダ

ファイルヘッダは最下位バイトを先頭置いた 32 ビットの整数値の並びからなります。

>     char header[4];			/* 常に "\1fcp" */
>     lsbint32 table_count;
>     struct toc_entry {
>         lsbint32 type;		/* 下記参照, どのテーブルかを指定 */
>         lsbint32 format;		/* 下記参照, データがテーブル内にどんなフォーマットで格納されるかを指定 */
>         lsbint32 size;		/* バイト数 */
>         lsbint32 offset;		/* ファイルの先頭から */
>     } tables[table_count];

type フィールドは以下のどれか 1 つです:

>     #define PCF_PROPERTIES		    (1<<0)
>     #define PCF_ACCELERATORS	    (1<<1)
>     #define PCF_METRICS		    (1<<2)
>     #define PCF_BITMAPS		    (1<<3)
>     #define PCF_INK_METRICS		    (1<<4)
>     #define	PCF_BDF_ENCODINGS	    (1<<5)
>     #define PCF_SWIDTHS		    (1<<6)
>     #define PCF_GLYPH_NAMES		    (1<<7)
>     #define PCF_BDF_ACCELERATORS	    (1<<8)

format フィールドは以下のどれか 1 つです:

>     #define PCF_DEFAULT_FORMAT	0x00000000
>     #define PCF_INKBOUNDS		0x00000200
>     #define PCF_ACCEL_W_INKBOUNDS	0x00000100
>     #define PCF_COMPRESSED_METRICS	0x00000100

format フィールドは以下のフラグで修飾可能です:

>     #define PCF_GLYPH_PAD_MASK	(3<<0)		/* 説明はビットマップテーブルの項を参照 */
>     #define PCF_BYTE_MASK		(1<<2)		/* 上位バイトが先か */
>     #define PCF_BIT_MASK		(1<<3)		/* 上位ビットが先か */
>     #define PCF_SCAN_UNIT_MASK	(3<<4)		/* 説明はビットマップテーブルの項を参照 */

format フィールドは、各テーブルの最初のワードとして繰り返されます。ほとんどのテーブルは 1 種類のフォーマット (デフォルト) しか含んでいませんが、フォントによっては異なるフォーマットを使用しています。format の上位の 3 バイトが、全体のフォーマットを記述します。整数とビットが格納される方式は、上のマスクビットの 1 つを加えることによって変更することができます。

すべてのテーブルは 32 ビット境界から始まります (端数は 0 でパディングされます)。

## 属性テーブル

>     lsbint32 format; 		/* 常に最下位ビットが最初に格納される! */
>     int32 nprops;			/* format で指定されたバイトオーダで格納される */
>     struct props {
>         int32 name_offset;		/* 以下の文字列テーブルへのオフセット */
>         int8 isStringProp;
>         int32 value;		/* 整数属性の即値, 文字列属性のオフセット */
>     } props[nprops];
>     char padding[(nprops&3)==0?0:(4-(nprops&3))];	/* 次の int32 境界まで埋める */
>     int string_size;		/* 文字列の総サイズ (末尾の NUL を含む) */
>     char strings[string_size];
>     char padding2[];

これらの属性は、X がユーザに提供するフォントアトムです。これらの多くは xc/doc/specs/XLFD/xlfd.tbl.ms またはこの文書で解説されています。 (X プロトコルはこれらのアトムに制限を加えていないので、第三者が何らかのフォントの定義を行うことができます)

属性の名前は、`strings + props[i].name_offset` に書かれています。

## メトリックのデータ

いくつかのテーブル (PCF_METRICS, PCF_INK_METRICS およびアクセラレータテーブルの内部) には、圧縮フォーマット (PCF_COMPRESSED_METRICS) または非圧縮フォーマット (DEFAULT) のどちらかでメトリックデータが格納されています。圧縮フォーマットは、値を格納するのに byte 型を使用するのに対し、非圧縮フォーマットは short 型を使用します。(圧縮された) バイト値は符号なし byte 値で、0x80 のオフセットが加えられています (よって、実際の値は `(getc(pcf_file)-0x80)` になります)。データは以下のように格納されています:
圧縮フォーマット

>     uint8 left_sided_bearing;
>     uint8 right_side_bearing;
>     uint8 character_width;
>     uint8 character_ascent;
>     uint8 character_descent;
>      /* 暗黙の文字属性フィールド = 0 */

非圧縮フォーマット:

>     int16 left_sided_bearing;
>     int16 right_side_bearing;
>     int16 character_width;
>     int16 character_ascent;
>     int16 character_descent;
>     uint16 character_attributes;

これは、XCharStruct で必要とされるデータを提供します。

## アクセラレータテーブル

これらのデータは、フォントの全体に関わる多数の細々とした情報を提供します。個のデータ構造は PCF_ACCELERATORS と PCF_BDF_ACCELERATORS の 2 個のテーブルで使用されます。テーブルは DEFAULT か PCF_ACCEL_W_INKBOUNDS のいずれかのフォーマットを使用することができます (後者の場合、最後にいくつかの拡張メトリックデータが追加されます)。

アクセラレータテーブルは以下のような形をしています: 両方のテーブルが存在する場合、BDF アクセラレータのほうが標準アクセラレータよりも優先されます。BDF アクセラレータはフォント内の符号化された文字を参照するデータのみを含みます (それに対し、単純アクセラレータテーブルは全てのグリフを含むので、BDF アクセラレータの方がより正確なのです)。

## メトリックテーブル

メトリックテーブルには PCF_METRICS と PCF_INK_METRICS の異なる 2 種類のテーブルが存在します。前者には、格納されたビットマップのサイズを含んでいるのに対し、後者は最小バウンディングボックスを含みます。両者は同じデータを含むことができますが、多くの CJK フォントはビットマップにパディングをしているため、すべてのビットマップは同じサイズです。テーブルフォーマットは DEFAULT または PCF_CONPRESSED_METRICS のどちらかが使用可能です (これの説明は、メトリックデータ に関するセクションを参照してください)。

>     lsbint32 format; 		/* 常に最下位ビットが最初に格納される! */
>     /* フォーマットが compressed の場合 */
>         int16 metrics_count;
>         Compressed_Metrics metrics[metrics_count];
>     /* それ以外で、フォーマットがデフォルト (uncompressed) の場合 */
>         int32 metrics_count;
>         Uncompressed_Metrics metrics[metrics_count];
>     /* endif */

## ビットマップテーブル

ビットマップテーブルのタイプは PCF_BITMAPS です。フォーマットは PCF_DEFAULT でなければなりません。

>     lsbint32 format; 		/* 常に最下位ビットが最初に格納される! */
>     int32 glyph_count;		/* バイトオーダは format に依存する。メトリックの個数と同じになるべき */
>     int32 offsets[glyph_count];	/* ビットマップデータへのバイトオフセット */
>     int32 bitmapSizes[4];		/* 各種パディングオプションに依存するビットマップデータのサイズ */
>     				/*  どのオプションが使われているかは (format&3) で指定している */
>     char bitmap_data[bitmapsizes[format&3]];	/* ビットマップデータ。format は以下のフラグを含む: */
>     				/* バイトオーダ (format&4 => 最上位バイトが先頭)*/
>     				/* ビットオーダ (format&8 => 最上位ビットが先頭) */
>     				/* 各グリフのビットマップの各列をどうパディングするか (format&3) */
>     				/*  0=>byte毎, 1=>short毎, 2=>int毎 */
>     				/* ビットが (byte, short, int の)どの単位で格納されるか  (format>>4)&3 */
>     				/*  0=>byte単位, 1=>short単位, 2=>int単位 */

## エンコーディングテーブル

エンコーディングテーブルは PCF_BDF_ENCODINGS 型です。フォーマットは PCF_DEFAULT でなければなりません。

>     lsbint32 format; 		/* 常に最下位ビットが最初に格納される! */
>     int16 min_char_or_byte2;	/* XFontStruct のとおり */
>     int16 max_char_or_byte2;	/* XFontStruct のとおり */
>     int16 min_byte1;		/* XFontStruct のとおり */
>     int16 max_byte1;		/* XFontStruct のとおり */
>     int16 default_char;		/* XFontStruct のとおり */
>     int16 glyphindeces[(max_char_or_byte2-min_char_or_byte2+1)*(max_byte1-min_byte1+1)];
>     				/* 各符号位置に対応するグリフインデックス */
>     				/* 値 0xffff は、その符号位置にグリフが存在しないことを表す */

1 バイトエンコーディングでは min_byte1==max_byte1==0 であり、符号位置の値は [min_char_or_byte2,max_char_or_byte2] の範囲に収まります。ある符号位置が値 encoding であるとき、対応するグリフインデックスは glyphindex[encoding-min_char_or_byte2] になります。

それ以外の場合、[min_byte1,max_byte1] は、2 バイトエンコーディングの 1 バイト目 (上位バイト) の取ることのできる値の範囲を指定し、一方 [min_char_or_byte2,max_char_or_byte2] が 2 バイト目の範囲を指定します。2 バイトエンコーディング (enc1, enc2) に対応するグリフインデックスは、glyph_index[(enc1-min_byte1)*(max_char_or_byte2-min_char_or_byte2+1)+enc2-min_char_or_byte2] になります。

すべてのグリフに文字符号を割り当てる必要はありません。すべての符号位置にグリフを割り当てる必要はありません。

## スケーラブルな幅のテーブル

スケーラブルな幅のテーブルは PCF_SWIDTH です。フォーマットは PCF_DEFAULT でなければなりません。

>     lsbint32 format; 		/* 常に最下位ビットが最初に格納される! */
>     int32 glyph_count;		/* バイトオーダは format に依存する。メトリックの個数と同じになるべき */
>     int32 swidths[glyph_count];	/* ビットマップデータへのバイトオフセット */

スケーラブルな文字幅は、em ユニットで表した対応する PostScript 文字の幅 (em の 1/1000) です。

## グリフ名テーブル

グリフ名テーブルは PCF_GLYPH_NAMES 型です。フォーマットは PCF_DEFAULT でなければなりません。

>     lsbint32 format; 		/* 常に最下位ビットが最初に格納される! */
>     int32 glyph_count;		/* バイトオーダは format に依存する。メトリックの個数と同じになるべき */
>     int32 offsets[glyph_count];	/* 文字列データへのバイトオフセット */
>     int32 string_size;
>     char string[string_size];

各文字につけられた PostScript 名です。

その他の情報源:

- http://www.tsg.ne.jp/GANA/S/pcf2bdf/pcf.pdf
- http://myhome.hananet.net/~bumchul/xfont/pcf.txt